#!/usr/bin/env python3

class Error(BaseException):
	pass

class Tokeniser:
	def __init__(self):
		pass

	def tokenise(self, source):
		tokens = []
		escaped = False
		buf = ""
		for char in source:
			if not escaped and char in ';,=:[]\\':
				if char == '\\':
					escaped = True
				else:
					if len(buf):
						tokens.append(buf)
						buf = ''
					tokens.append(char)
			else:
				escaped = False
				buf += char
		if escaped:
			raise Error("unterminated escape at end of input")
		if len(buf):
			tokens.append(buf)
		return tokens

class Parser:
	def __init__(self):
		self.interesting = ";,=:[]"
		self.tokeniser = Tokeniser()

	def parse(self, source):
		tokens = self.tokeniser.tokenise(source)
		stack = [[]]
		result = []
		paired = False
		for token in tokens:
			if token in self.interesting:
				if token == ';':
					paired = False
					if len(stack) != 1:
						raise Error("mismatched '[' in source")
					result.append(stack[0])
					stack = [[]]
				elif token == ',':
					paired = False
				elif token == '=' or token == ':':
					if paired:
						raise Error("attempt to add another value to key-value pair")
					else:
						paired = True
				elif token == '[':
					paired = False
					stack.append([])
				elif token == ']':
					paired = False
					if len(stack) < 2:
						raise Error("mismatched ']' in source")
					top = stack.pop()
					stack[-1].append(top)
			else:
				if paired:
					stack[-1][-1] = (stack[-1][-1], token)
				else:
					stack[-1].append(token)
		if len(stack) > 1:
			raise Error("mismatched '[' in source")
		elif len(stack) < 1:
			raise Error("mismatched ']' in source")
		else:
			result.append(stack[0])
		return result
